package br.eng.eliseu.gwt.gestaoWeb.server.service.cadastro;

import java.util.List;

import br.eng.eliseu.gwt.gestaoWeb.client.service.CadastroService;
import br.eng.eliseu.gwt.gestaoWeb.client.ui.sistema.configuracoes.PerfilUsuarioViewVO;
import br.eng.eliseu.gwt.gestaoWeb.client.ui.site.cadastro.PrimeiroCadastroViewVO;
import br.eng.eliseu.gwt.gestaoWeb.model.UsuarioAutenticadoVO;
import br.eng.eliseu.gwt.gestaoWeb.model.empresa.Empresa;
import br.eng.eliseu.gwt.gestaoWeb.model.empresa.EmpresaSistema;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Cidade;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Endereco;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Estado;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Pais;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.TipoEnderecoEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.TipoLogradouro;
import br.eng.eliseu.gwt.gestaoWeb.model.enums.StatusEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.Pessoa;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.PessoaDocumento;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.PessoaEndereco;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.PessoaFone;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.TipoDocumentoEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.TipoFoneEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.TipoPessoaEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.usuario.DireitoUsuarioEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.usuario.StatusUsuarioEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.usuario.Usuario;
import br.eng.eliseu.gwt.gestaoWeb.model.usuario.UsuarioSistema;
import br.eng.eliseu.gwt.gestaoWeb.server.command.generico.GetEntityListCommand;
import br.eng.eliseu.gwt.gestaoWeb.server.command.generico.SaveEntityCommand;
import br.eng.eliseu.gwt.gestaoWeb.server.command.perfil.PerfilUsuarioSalvarCommand;
import br.eng.eliseu.gwt.gestaoWeb.server.util.DateUtilServer;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;

@Singleton
public class CadastroServiceImpl extends RemoteServiceServlet implements CadastroService {

	private static final long serialVersionUID = -2350607266406997928L;

	@Inject Injector injector;

	@SuppressWarnings("unchecked")
	public UsuarioAutenticadoVO salvaCadastroGratis(PrimeiroCadastroViewVO vo) throws Exception {

		Pais pais = getPais(vo.getPais());
		Estado estado = getEstado(pais, vo.getEstado());
		Cidade cidade = getCidade(estado, vo.getCidade());
		TipoLogradouro tipoLogradouro = getOrSaveTipoLogradouro(vo.getTipoLogradouro());

		GetEntityListCommand cmd;
		Endereco endereco = new Endereco();
		Empresa empresa = new Empresa();
		Pessoa pessoa = new Pessoa();
		PessoaDocumento pessoaDocumento = new PessoaDocumento();
		PessoaFone pessoaFone = new PessoaFone();
		PessoaEndereco pessoaEndereco = new PessoaEndereco();
		Usuario usuario = new Usuario();
		EmpresaSistema empresaSistema = new EmpresaSistema();
		UsuarioSistema usuarioSistema = new UsuarioSistema();

		/*
		 * Pega e entidade TipoLogradouro
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("tipoLogradouro.porNomeAbreviado");
		cmd.addParameter("nomeAbreviado", vo.getTipoLogradouro());
		cmd.setMaxResults(1);
		List<TipoLogradouro> lTipoLogradouro = cmd.call();
		if (lTipoLogradouro.size() > 0) {
			tipoLogradouro = lTipoLogradouro.get(0);
		} else {
			tipoLogradouro.setNome(vo.getTipoLogradouro());
			tipoLogradouro.setNomeAbreviado(vo.getTipoLogradouro());

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(tipoLogradouro);
			tipoLogradouro = (TipoLogradouro) cmdSave.call();
		}

		/*
		 * Pega e entidade Endereco
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("endereco.porCidadeLogradouroNumero");
		cmd.addParameter("cidade", cidade);
		cmd.addParameter("logradouro", vo.getLogradouro());
		cmd.addParameter("numero", vo.getNumero());
		cmd.setMaxResults(1);
		List<Endereco> lEndereco = cmd.call();
		if (lEndereco.size() > 0) {
			endereco = lEndereco.get(0);
		} else {
//			endereco.setTipo(TipoEnderecoEnum.COMERCIAL);
//			endereco.setPrincipal(true);
			endereco.setCep(vo.getCep());
			endereco.setTipoLogradouro(tipoLogradouro);
			endereco.setLogradouro(vo.getLogradouro());
			endereco.setNumero(vo.getNumero());
			endereco.setComplemento(vo.getComplemento());
			endereco.setBairro(vo.getBairro());
			endereco.setCidade(cidade);
			endereco.setEstado(estado);

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(endereco);
			endereco = (Endereco) cmdSave.call();
		}
		
		/* Pega e entidade Empresa
		 */
		String e = vo.getEmpresa().toUpperCase().trim();
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("empresa.porDocumento");
		cmd.addParameter("documento", vo.getDocEmpresa());
		cmd.setMaxResults(1);
		List<Empresa> lEmpresa = cmd.call();
		if (lEmpresa.size() > 0) {
			empresa = lEmpresa.get(0);
		} else {
			empresa.setNome(e);
			empresa.setStatus(StatusEnum.ATIVO);
			empresa.setTipoPessoa(vo.getTipoPessoa());
			empresa.setDocumento(vo.getDocEmpresa());
			empresa.setEndereco(endereco);
			empresa.setTelefone(vo.getTelefone());

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(empresa);
			empresa = (Empresa) cmdSave.call();
		}

		/*
		 * Pega e entidade Pessoa
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("pessoaDocumento.porDocumento");
		cmd.addParameter("tipoDocumento", TipoDocumentoEnum.CPF);
		cmd.addParameter("documento", vo.getDocUsuario());
		cmd.setMaxResults(1);
		List<PessoaDocumento> lPessoaDocumento = cmd.call();
		if (lPessoaDocumento.size() > 0) {
			pessoaDocumento = lPessoaDocumento.get(0);
			pessoa = pessoaDocumento.getPessoa();
		} else {
			/*
			 * Inclui Pessoa
			 */
			pessoa.setEmpresa(empresa);
			pessoa.setNome(vo.getNomeCompleto());
			pessoa.setTipoPessoa(TipoPessoaEnum.FISICA);
			pessoa.setDtNascimento(vo.getNascimento());

			SaveEntityCommand cmdSave;
			cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(pessoa);
			pessoa = (Pessoa) cmdSave.call();

			/*
			 * Inclui CPF da Pessoa
			 */
			pessoaDocumento.setPessoa(pessoa);
			pessoaDocumento.setTipoDocumento(TipoDocumentoEnum.CPF);
			pessoaDocumento.setDocumento(vo.getDocUsuario());

			cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(pessoaDocumento);
			pessoaDocumento = (PessoaDocumento) cmdSave.call();

		}

		/*
		 * Salva Telefone da Pessoa
		 */
		if (vo.getTelefone() != null && !"".equals(vo.getTelefone())) {
			cmd = injector.getInstance(GetEntityListCommand.class);
			cmd.setNamedQuery("pessoaFone.porPessoaTipoFone");
			cmd.addParameter("pessoa", pessoa);
			cmd.addParameter("tipoFone", TipoFoneEnum.CELULAR);
			cmd.addParameter("fone", vo.getTelefone());
			cmd.setMaxResults(1);
			List<PessoaFone> lPessoaFone = cmd.call();
			if (lPessoaFone.size() > 0) {
				pessoaFone = lPessoaFone.get(0);
			} else {
				pessoaFone.setPessoa(pessoa);
				pessoaFone.setTipoFone(TipoFoneEnum.CELULAR);
				pessoaFone.setFone(vo.getTelefone());
				pessoaFone.setPrincipal(true);

				SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
				cmdSave.setBaseEntity(pessoaFone);
				pessoaFone = (PessoaFone) cmdSave.call();
			}
		}

		/* Salva Endereco Pessoa
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("pessoaEndereco.porPessoaEndereco");
		cmd.addParameter("pessoa", pessoa);
		cmd.addParameter("endereco", endereco);
		cmd.setMaxResults(1);
		List<PessoaEndereco> lPessoaEndereco = cmd.call();
		if (lPessoaEndereco.size() > 0) {
			pessoaEndereco = lPessoaEndereco.get(0);
		} else {
			pessoaEndereco.setTipoEndereco(TipoEnderecoEnum.COMERCIAL);
			pessoaEndereco.setPrincipal(true);
			pessoaEndereco.setPessoa(pessoa);
			pessoaEndereco.setEndereco(endereco);

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(pessoaEndereco);
			pessoaEndereco = (PessoaEndereco) cmdSave.call();
		}


		
		/*
		 * Pega e entidade Usuario
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("usuario.porPessoa");
		cmd.addParameter("pessoa", pessoa);
		cmd.setMaxResults(1);
		List<Usuario> lUsuario = cmd.call();
		if (lUsuario.size() > 0) {
			usuario = lUsuario.get(0);
		} else {
			usuario.setPessoa(pessoa);
			usuario.setNome(vo.getUsuario());
			usuario.setSenha(vo.getSenha());
			usuario.setDtInicio(DateUtilServer.dataAtual());

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(usuario);
			usuario = (Usuario) cmdSave.call();
		}

		/*
		 * Pega e entidade EmpresaSistema
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("empresaSistema.porEmpresaSistema");
		cmd.addParameter("empresa", empresa);
		cmd.addParameter("sistema", vo.getSistema());
		cmd.setMaxResults(1);
		List<EmpresaSistema> lEmpresaSistema = cmd.call();
		if (lEmpresaSistema.size() > 0) {
			empresaSistema = lEmpresaSistema.get(0);
		} else {
			empresaSistema.setEmpresa(empresa);
			empresaSistema.setSistema(vo.getSistema());
			empresaSistema.setStatus(StatusEnum.ATIVO);
			empresaSistema.setDtInicio(DateUtilServer.dataAtual());

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(empresaSistema);
			empresaSistema = (EmpresaSistema) cmdSave.call();
		}

		/*
		 * Pega e entidade UsuarioSistema
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("usuarioSistema.porUsuarioSistema");
		cmd.addParameter("usuario", usuario);
		cmd.addParameter("empresaSistema", empresaSistema);
		cmd.setMaxResults(1);
		List<UsuarioSistema> lUsuarioSistema = cmd.call();
		if (lUsuarioSistema.size() > 0) {
			usuarioSistema = lUsuarioSistema.get(0);
		} else {
			usuarioSistema.setUsuario(usuario);
			usuarioSistema.setEmpresaSistema(empresaSistema);
			usuarioSistema.setEmail(vo.getEmail());
			usuarioSistema.setDireito(DireitoUsuarioEnum.DONO);
			usuarioSistema.setStatus(StatusUsuarioEnum.ATIVO);
			usuarioSistema.setDtInicio(DateUtilServer.dataAtual());

			SaveEntityCommand cmdSave = injector.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(usuarioSistema);
			usuarioSistema = (UsuarioSistema) cmdSave.call();
		}

		UsuarioAutenticadoVO usrVO = new UsuarioAutenticadoVO();
		usrVO.setUsuarioAutenticado(usuarioSistema);

		return usrVO;
	}

	/*
	 * Pega a entidade Pais
	 */
	@SuppressWarnings("unchecked")
	private Pais getPais(String pais) {
		GetEntityListCommand cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("pais.porNome");
		cmd.addParameter("nome", pais);
		cmd.setMaxResults(1);
		List<Pais> lPais = cmd.call();
		if (lPais.size() > 0) {
			return lPais.get(0);
		}
		return null;
	}

	/*
	 * Pega e entidade Estado
	 */
	@SuppressWarnings("unchecked")
	private Estado getEstado(Pais pais, String siglaEstado) {
		GetEntityListCommand cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("estado.porPaisHeSigla");
		cmd.addParameter("pais", pais);
		cmd.addParameter("sigla", siglaEstado);
		cmd.setMaxResults(1);
		List<Estado> lEstado = cmd.call();
		if (lEstado.size() > 0) {
			return lEstado.get(0);
		}
		return null;
	}

	/*
	 * Pega e entidade Cidade
	 */
	@SuppressWarnings("unchecked")
	private Cidade getCidade(Estado estado, String cidade) {
		GetEntityListCommand cmd = injector
				.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("cidade.porEstadoLikeNome");
		cmd.addParameter("estado", estado);
		cmd.addParameter("nome", cidade);
		cmd.setMaxResults(1);
		List<Cidade> lCidade = cmd.call();
		if (lCidade.size() > 0) {
			return lCidade.get(0);
		}
		return null;
	}

	/*
	 * Pega e entidade TipoLogradouro
	 */
	@SuppressWarnings("unchecked")
	private TipoLogradouro getOrSaveTipoLogradouro(String tipoLogradouro) {
		TipoLogradouro tl = new TipoLogradouro();
		tipoLogradouro = tipoLogradouro.toUpperCase().trim();
		GetEntityListCommand cmd = injector
				.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("tipoLogradouro.porNomeAbreviado");
		cmd.addParameter("nomeAbreviado", tipoLogradouro);
		cmd.setMaxResults(1);
		List<TipoLogradouro> lTipoLogradouro = cmd.call();
		if (lTipoLogradouro.size() > 0) {
			tl = lTipoLogradouro.get(0);
		} else {
			tl.setNome(tipoLogradouro);
			tl.setNomeAbreviado(tipoLogradouro);

			SaveEntityCommand cmdSave = injector
					.getInstance(SaveEntityCommand.class);
			cmdSave.setBaseEntity(tl);
			tl = (TipoLogradouro) cmdSave.call();
		}
		return tl;
	}

	@SuppressWarnings("unchecked")
	public PerfilUsuarioViewVO carregaPerfil(Usuario usuario) throws Exception {
		
		PerfilUsuarioViewVO perfil = new PerfilUsuarioViewVO();
		GetEntityListCommand cmd;

		perfil.setUsuario(usuario);

		/* Carrega Documentos
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("pessoaDocumento.porPessoa");
		cmd.addParameter("pessoa", usuario.getPessoa());
		List<PessoaDocumento> lPessoaDocumento = cmd.call();
		for (PessoaDocumento pd : lPessoaDocumento) {
			perfil.getPessoaDocumentoList().add(pd);
		}
		
		/* Carrega Telefones
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("pessoaFone.porPessoa");
		cmd.addParameter("pessoa", usuario.getPessoa());
		List<PessoaFone> lPessoaFone = cmd.call();
		for (PessoaFone pf : lPessoaFone) {
			perfil.getPessoaFoneList().add(pf);
		}

		/* Carrega Endereco
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("pessoaEndereco.porPessoa");
		cmd.addParameter("pessoa", usuario.getPessoa());
		List<PessoaEndereco> lPessoaEndereco = cmd.call();
		for (PessoaEndereco pe : lPessoaEndereco) {
			perfil.getPessoaEnderecoList().add(pe);
		}

		/* Carrega UsuarioSistema
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("usuarioSistema.porUsuarioTodos");
		cmd.addParameter("usuario", usuario);
		List<UsuarioSistema> lUsuarioSistema = cmd.call();
		for (UsuarioSistema o : lUsuarioSistema) {
			perfil.getUsuarioSistemaList().add(o);
		}
		
		return perfil;
	}

	@Transactional
	public PerfilUsuarioViewVO gravaPerfil(PerfilUsuarioViewVO perfil) throws Exception {

		PerfilUsuarioSalvarCommand cmd = injector.getInstance(PerfilUsuarioSalvarCommand.class);
		cmd.setVo(perfil);
		PerfilUsuarioViewVO vo = cmd.call();
		return vo;
		
		
	}

	@SuppressWarnings("unchecked")
	public Empresa getEmpresa(String docEmpresa) throws Exception {
		GetEntityListCommand cmd;
		Empresa e;
		
		/* Pega e entidade Empresa
		 */
		cmd = injector.getInstance(GetEntityListCommand.class);
		cmd.setNamedQuery("empresa.porDocumento");
		cmd.addParameter("documento", docEmpresa);
		cmd.setMaxResults(1);
		List<Empresa> lEmpresa = cmd.call();
		e = null;
		if (lEmpresa.size() > 0) {
			e = lEmpresa.get(0);
		} else {
			throw new Exception("Empresa não cadastrada");
		}

		return e;
	}

}
